using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using XnaUtility.AI.FSM;
using XnaUtility.Control;

namespace XnaUtility.ScreenManagement
{
    public class ScreenBrain : IBrain
    {
        public Game game;
        public InputBase input;
        public Stack<int> returnStack;
        public bool clearStack = false;

        public void UpdatePerception(GameTime gameTime)
        {
        }

        public void Init()
        {
            input = (InputBase)game.Services.GetService(typeof(InputBase));
            returnStack = new Stack<int>();
        }
    }
    

    public abstract class Screen_FSM : FSM_Machine
    {

        ScreenBrain scrnBrain;

        public Screen_FSM(Game newGameScreen)
            : base(null)
        {
            scrnBrain = new ScreenBrain();
            scrnBrain.game = newGameScreen;
            scrnBrain.Init();
           
        }

        public override int CheckTransitions()
        {
            targetStateID = curState.CheckTransitions();
            if (targetStateID != curStateID)
            {
                targetState = states[targetStateID];
                curState.OnExit();
                targetState.OnEnter();
                curState = targetState;
                curStateID = curState.StateID;
            }

            if (scrnBrain.clearStack)
            {
                //need to re-init all states in the stack
                while (scrnBrain.returnStack.Count > 0)
                {
                    int key = scrnBrain.returnStack.Pop();
                    states[key].Init();
                }

                scrnBrain.clearStack = false;
            }

            return 0;
        }

        public override void UpdateMachine(GameTime gameTime)
        {
            if (states.Count == 0) return;      //nothing to do

            foreach (int key in states.Keys)
            {
                if (((ScreenState)states[key]).canUpdate)
                    states[key].Update(gameTime);
            }

            CheckTransitions();
        }

        public override void OnEnter()
        {
            base.OnEnter();
        }

        public override void OnExit()
        {
            base.OnExit();
        }

        public override void Update(GameTime gameTime)
        {
            base.Update(gameTime);
        }

        public void Draw(SpriteBatch spriteBatch)
        {
            foreach (int key in states.Keys)
            {
                if (((ScreenState)states[key]).canDraw)
                    ((ScreenState)states[key]).Draw(null, spriteBatch);
            }
        }
    }
}
